<template>
  <!---搜索表单-->
    <div class="search-div">
        <el-form label-width="70px" size="small">
            <el-row>
                <el-col :span="8">
                    <el-form-item label="学生姓名">
                        <el-input v-model="queryDto.name" style="width: 100%" placeholder="请输入学生姓名"></el-input>
                    </el-form-item>
                </el-col>
                <el-col :span="8">
                    <el-form-item label="学生学号">
                        <el-input v-model="queryDto.studentNumber" style="width: 100%"
                                  placeholder="请输入学生学号"></el-input>
                    </el-form-item>
                </el-col>
                <el-col :span="8">
                    <el-form-item label="所属学院">
                        <el-select v-model="queryDto.collegeId" style="width: 100%" placeholder="请选择或输入学院"
                                   filterable>
                            <el-option v-for="item in collegeList" :key="item.id" :value="item.id"
                                       :label="item.name"></el-option>
                        </el-select>
                    </el-form-item>
                </el-col>
                <el-col :span="8">
                    <el-form-item label="所属专业">
                        <el-select v-model="queryDto.majorId" style="width: 100%" placeholder="请选择或输入专业"
                                   filterable>
                            <el-option v-for="item in majorList" :key="item.id" :value="item.id"
                                       :label="item.name"></el-option>
                        </el-select>
                    </el-form-item>
                </el-col>
                <el-col :span="8">
                    <el-form-item label="所属班级">
                        <el-select v-model="queryDto.classesId" style="width: 100%" placeholder="请选择或输入班级"
                                   filterable>
                            <el-option v-for="item in classList" :key="item.id" :value="item.id"
                                       :label="item.name"></el-option>
                        </el-select>
                    </el-form-item>
                </el-col>
            </el-row>
            <el-row style="display:flex">
                <el-button type="primary" size="small" @click="searchStudent"> 搜索</el-button>
                <el-button size="small" @click="resetData">重置</el-button>
            </el-row>
        </el-form>
    </div>

  <!--添加按钮-->
    <div class="tools-div">
        <el-button type="success" size="small" @click="addShow"> 单个添加</el-button>
        <el-button type="primary" size="small" @click="importData"> 批量添加</el-button>
        <el-button type="danger" size="small" @click="deleteSelected"> 批量删除</el-button>
        <el-button type="primary" size="small" @click="toggleSelection"> 取消选中</el-button>
        <el-button type="primary" size="small" @click="exportCsv">导出信息</el-button>
    </div>

    <el-dialog v-model="dialogImportVisible" title="导入文件（需选中班级）" width="45%" draggable>
        <el-form label-width="120px">
            <el-form-item label="导入的班级">
                <el-cascader v-model="classesId" :options="cascaderOptions" style="width: 100%;"
                             @change="handleClassSelectionChange" placeholder="请选择班级">
                </el-cascader>
                <router-link :to="{name: 'classes'}" style="color: #ee5252" text="没有找到班级?去添加班级"/>
            </el-form-item>
            <el-form-item label="学生信息文件" style="width: 100%;">
                <el-row :gutter="20">
                    <el-col :span="12">
                        <el-button size="small" type="success" @click="downloadTemplate">下载模板
                        </el-button>
                    </el-col>
                    <el-col :span="12">
                        <el-upload class="upload-demo" :before-upload="beforeUpload"
                                   :action="`http://localhost:8501/admin/school/student/importData?classesId=${upclass}`"
                                   :on-success="onUploadSuccess" :limit="1" :headers="headers">
                            <el-button size="small" type="primary">上传文件</el-button>
                        </el-upload>
                    </el-col>
                </el-row>
            </el-form-item>
        </el-form>
    </el-dialog>

    <el-dialog v-model="dialogVisible" title="添加或修改" width="40%" @close="handleDialogClose">
        <el-form label-width="120px" ref="ruleFormRef" :model="ruleForm" :rules="rules">
            <el-form-item label="学生姓名" prop="name">
                <el-input v-model="student.name" placeholder="请输入学生姓名"/>
            </el-form-item>
            <el-form-item label="学号" prop="studentNumber">
                <el-input v-model="student.studentNumber" :disabled="disabled"
                          placeholder="请输入学号"/>
            </el-form-item>
            <el-form-item label="性别">
                <el-radio-group v-model="student.sex">
                    <el-radio :label="1">男</el-radio>
                    <el-radio :label="0">女</el-radio>
                </el-radio-group>
            </el-form-item>
            <el-form-item label="身份证号" prop="idCard">
                <el-input v-model="student.idCard" placeholder="请输入身份证号"/>
            </el-form-item>
            <el-form-item label="联系方式" prop="contactInformation">
                <el-input v-model="student.contactInformation" placeholder="联系方式:手机号 或  电子邮箱"/>
            </el-form-item>
            <el-form-item label="出生日期" prop="birthday">
                <el-date-picker v-model="student.birthday" arrow-control placeholder="请选择日期"/>
            </el-form-item>
            <el-form-item label="所属班级" prop="classesId">
                <el-cascader style="width: 100%;" v-model="student.classesId"
                             :options="cascaderOptions" placeholder="请选择所属班级"/>
            </el-form-item>
            <el-form-item label="家庭住址" prop="address">
                <el-input v-model="student.address" placeholder="请输入家庭住址"/>
            </el-form-item>
            <el-form-item>
                <el-button type="primary" :disabled="!student.classesId" @click="submit">提交</el-button>
                <el-button @click="dialogVisible = false">取消</el-button>
            </el-form-item>
        </el-form>
    </el-dialog>

  <!---数据表格-->
    <el-table :data="list" style="width: 100%" border
              @selection-change="handleSelectionChange" ref="multipleTableRef">
        <el-table-column type="selection" width="55"/> <!-- 添加复选框列 -->
        <el-table-column prop="studentNumber" label="学号" sortable min-width="120px"/>
        <el-table-column prop="name" label="学生姓名" min-width="120px"/>
        <el-table-column prop="sex" label="性别" #default="scope" align="center">
            {{ scope.row.sex == 1 ? '男' : '女' }}
        </el-table-column>
        <el-table-column prop="idCard" label="身份证号" min-width="170px"/>
        <el-table-column prop="contactInformation" label="联系方式" min-width="130px"/>
        <el-table-column prop="birthday" label="出生日期" min-width="100px" align="center" :formatter="formatBirthday"/>
        <el-table-column prop="majorName" label="所属专业" sortable min-width="240px"/>
        <el-table-column prop="className" label="所属班级" sortable min-width="200px"/>
        <el-table-column prop="collegeName" label="所属学院" sortable min-width="200px"/>
        <el-table-column prop="address" label="家庭住址" min-width="350px"/>
        <el-table-column prop="createTime" label="创建时间" min-width="160px" align="center"/>
        <el-table-column prop="updateTime" label="更新时间" min-width="160px" align="center"/>
        <el-table-column label="操作" align="center" #default="scope" width="140px" fixed="right">
            <el-button type="primary" size="small" @click="editStudent(scope.row)"> 修改</el-button>
            <el-button type="danger" size="small" @click="deleteById(scope.row)"> 删除</el-button>
        </el-table-column>
    </el-table>
    <el-pagination v-model:current-page="pageParams.page" v-model:page-size="pageParams.limit"
                   :page-sizes="[5, 10, 20, 50, 100]" @size-change="fetchData" @current-change="fetchData"
                   layout="total, sizes, prev, pager, next" :total="total"/>
</template>

<!-- script部分修改内容 -->
<script setup>
import {onMounted, reactive, ref, watch} from 'vue'
import {
    DeleteStudentByStudentNumber,
    DeleteStudents,
    GetStudentListByPage,
    SaveStudent,
    UpdateStudent
} from '@/api/student'
import {ElMessage, ElMessageBox} from 'element-plus'
import {FindAllClass} from '@/api/classes'
import {useApp} from '@/pinia/modules/app'
import {GetAllCollege} from "@/api/college";
import {GetMagorListByCollegeId} from "@/api/major";
import * as XLSX from 'xlsx';

//表单数据模型
const ruleForm = ref({
    id: '',
    name: '',
    studentNumber: '',
    sex: '',
    idCard: '',
    contactInformation: '',
    birthday: null,
    classesId: '',
    address: ''
})
const student = ref(ruleForm) // 使用ref包裹该对象，使用reactive不方便进行重置
const collegeList = ref([])
const majorList = ref([])
const classList = ref([])

const classesId = ref('')
// 删除数据
const deleteById = row => {
    ElMessageBox.confirm('此操作将永久删除该记录, 是否继续?', 'Warning', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
    }).then(async () => {
        const {code} = await DeleteStudentByStudentNumber(row.studentNumber)
        if (code === 200) {
            ElMessage.success('删除成功')
            pageParams.value.page = 1
            await fetchData()
        }
    })
}
const multipleTableRef = ref([]);
const multipleSelection = ref([]);

const handleSelectionChange = (val) => {
    multipleSelection.value = val
}

const deleteSelected = async () => {
    const selectedRows = multipleSelection.value;
    if (selectedRows.length == 0) {
        ElMessage.warning('请选择要删除的记录')
        return;
    }
    ElMessageBox.confirm('此操作将永久删除该记录, 是否继续?', 'Warning', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
    }).then(async () => {
        const selectedIds = selectedRows.map(row => row.id);
        const {code} = await DeleteStudents(selectedIds)
        if (code === 200) {
            ElMessage.success('批量删除成功')
            pageParams.value.page = 1
            await fetchData()
        }
    })
}
// 取消选中
const toggleSelection = () => {
    multipleSelection.value = []; // 清空已选中的行
    const rows = multipleTableRef.value.store.states.data.value; // 获取表格中的数据
    rows.forEach(row => {
        multipleTableRef.value.clearSelection(row); // 清除每一行的选中状态
    });
};

// 修改按钮点击事件处理函数
const disabled = ref(false)
const editStudent = row => {
    student.value = row
    dialogVisible.value = true
    disabled.value = true
}
// 获取表单组件的引用
const ruleFormRef = ref('ruleFormRef');
const handleDialogClose = () => {
    // 清除验证状态
    ruleFormRef.value.clearValidate();
    student.value = {...ruleForm}; // 重置数据为默认值
    dialogVisible.value = false
    disabled.value = false
}
// 添加修改
const submit = async () => {
    ruleFormRef.value.validate(async (valid) => {
        if (valid) {
            if (student.value.classesId[2]) {
                student.value.classesId = student.value.classesId[2]
            }
            if (!student.value.id) {
                const {code} = await SaveStudent(student.value)
                if (code === 200) {
                    dialogVisible.value = false
                    ElMessage.success('操作成功')
                    await fetchData()
                }
            } else {
                const {code} = await UpdateStudent(student.value)
                if (code === 200) {
                    dialogVisible.value = false
                    ElMessage.success('操作成功')
                    await fetchData()
                }
            }
        } else {
            ElMessage.error('请填写完整')
            return false
        }
    })
}

// 分页条总记录数
let total = ref(0)
// 定义表格数据模型
let list = ref([])
// 控制对话是否展示的变量
const dialogVisible = ref(false)
//进入添加
const addShow = () => {
    dialogVisible.value = true
}
//分页数据
const pageParamsForm = {
    page: 1, // 页码
    limit: 10, // 每页记录数
}
const pageParams = ref(pageParamsForm) // 将pageParamsForm包装成支持响应式的对象
// 搜索表单数据
const queryDto = ref({
    name: '',
    studentNumber: '',
    collegeId: '',
    majorId: '',
    classesId: ''
})

// 搜索按钮点击事件处理函数
const searchStudent = () => {
    fetchData()
}

// 重置按钮点击事件处理函数
const resetData = () => {
    queryDto.value = {}
    fetchData()
    getMajorList()
    getClassList()
}

// 远程调用后端分页查询接口
const fetchData = async () => {
    const {data} = await GetStudentListByPage(
        pageParams.value.page,
        pageParams.value.limit,
        queryDto.value
    )
    list.value = data.list
    total.value = data.total
}
const rules =  {
    name: [{required: true, message: '请输入姓名', trigger: 'blur'}],
    studentNumber: [{required: true, message: '请输入学号', trigger: 'blur'}],
    idCard: [{required: true, message: '请输入身份证号', trigger: 'blur'}],
    contactInformation: [{required: true, message: '请输入联系方式', trigger: 'blur'}],
    birthday: [{required: true, message: '请选择出生日期', trigger: 'blur'}],
    classesId: [{required: true, message: '请选择所属班级', trigger: 'blur'}],
    address: [{required: true, message: '请输入家庭住址', trigger: 'blur'}],
}

const cascaderOptions = ref([])
const buildCascaderOptions = async () => {
    cascaderOptions.value = collegeList.value.filter(college => {
        // 检查学院是否有专业和班级
        const hasMajor = majorList.value.some(major => major.collegeId === college.id);
        const hasClass = classList.value.some(cls => {
            return majorList.value.some(major => major.id === cls.majorId && major.collegeId === college.id);
        });
        return hasMajor && hasClass; // 只保留有专业和班级的学院
    }).map(college => ({
        value: college.id,
        label: college.name,
        children: majorList.value.filter(major => major.collegeId === college.id)
            .map(major => ({
                value: major.id,
                label: major.name,
                children: classList.value.filter(cls => cls.majorId === major.id)
                    .map(classes => ({
                        value: classes.id,
                        label: classes.name
                    }))
            })).filter(major => major.children.length > 0) // 只保留有班级的专业
    }));
}


// 页面加载完毕以后请求后端接口获取数据
onMounted(async () => {
    await fetchData()
    await getCollegeList()
    await getMajorList()
    await getClassList()
    // 构建级联选择器的选项数据
    await buildCascaderOptions()
})

const getCollegeList = async () => {
    const {data} = await GetAllCollege()
    collegeList.value = data.map(college => {
        return {
            id: college.id,
            name: college.name
        }
    })
}
const getMajorList = async () => {
    const {data} = await GetMagorListByCollegeId(queryDto.value.collegeId)
    majorList.value = data.map(major => {
        return {
            id: major.id,
            name: major.name,
            collegeId: major.collegeId
        }
    })
}
const getClassList = async () => {
    const {data} = await FindAllClass(queryDto.value.collegeId, queryDto.value.majorId)
    classList.value = data.map(classes => {
        return {
            id: classes.id,
            name: classes.name,
            majorId: classes.majorId
        }
    });
}

watch(() => queryDto.value.collegeId,
    (newCollegeId, oldCollegeId) => {
        if (newCollegeId) {
            getMajorList(newCollegeId);
            getClassList(newCollegeId);
        }
    }
)
watch(() => queryDto.value.majorId,
    (newMajorId, oldMajorId) => {
        if (newMajorId) {
            getClassList(newMajorId);
        }
    }
)

//导出学生信息
const exportCsv = () => {
    if (list.value.length > 0) {
        // 拆分数据并设置表头
        const filteredData = list.value.map(item => ({
            '学号': item.studentNumber,
            '学生姓名': item.name,
            '性别': item.sex == 1 ? '男' : '女',
            '身份证号': item.idCard,
            '联系方式': item.contactInformation,
            '出生日期(****-**-**)': item.birthday,
            '所属专业': item.majorName,
            '所属班级': item.className,
            '所属学院': item.collegeName,
            '家庭住址': item.address
        }));
        const worksheet = XLSX.utils.json_to_sheet(filteredData);
        const workbook = XLSX.utils.book_new();
        XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
        XLSX.writeFile(workbook, '学生信息表.xlsx');
    } else {
        console.log('表格数据为空，无法导出！');
    }
}
// 文件上传相关变量以及方法定义
const dialogImportVisible = ref(false)
const upclass = ref('')
const importData = () => {
    dialogImportVisible.value = true
}
// 这里可以处理班级选择发生变化后的逻辑
const handleClassSelectionChange = () => {
    upclass.value = classesId.value[2]
}
const headers = {
    token: useApp().authorization.token, // 从pinia中获取token，在进行文件上传的时候将token设置到请求头中
}
const beforeUpload = (file) => {
    // 验证文件类型
    const fileType = file.type
    const fileTypes = ['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.ms-excel']
    if (!fileTypes.includes(fileType)) {
        ElMessage.error('请上传正确的文件格式')
        return false
    }
    // 验证文件大小
    const fileSize = file.size
    const maxSize = 2 * 1024 * 1024
    if (fileSize > maxSize) {
        ElMessage.error('文件大小不能超过2M')
        return false
    }
    if (upclass.value === '') {
        ElMessage.error('请选择班级')
        return false
    }
    return true
}

// 上传文件成功以后要执行方法
const onUploadSuccess = async (response, file) => {
    if (response.code === 200) {
        ElMessage.success('导入成功')
        await fetchData()
        dialogImportVisible.value = false
    } else {
        ElMessage.error('导入失败,请检查数据！')
    }
}
//下载模板
const downloadTemplate = async () => {
    // 拆分数据并设置表头
    const filteredData = {
        '学号': '',
        '学生姓名': '',
        '性别': '',
        '身份证号': '',
        '出生日期(****-**-**)': '',
        '联系方式': '',
        '家庭住址': ''
    }
    const worksheet = XLSX.utils.json_to_sheet([filteredData], {header: Object.keys(filteredData)});
    const workbook = XLSX.utils.book_new();
    XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
    XLSX.writeFile(workbook, '学生信息表.xlsx');
}
</script>

<style scoped>
.search-div {
    margin-bottom: 10px;
    padding: 10px;
    border: 1px solid #ebeef5;
    border-radius: 3px;
    background-color: #fff;
}

.tools-div {
    margin: 10px 0;
    padding: 10px;
    border: 1px solid #ebeef5;
    border-radius: 3px;
    background-color: #fff;
}
</style>
